<?php
/**
 * 项目中和客户端定义字段要求规范不一致
 * 客户端请求字段名 是驼峰
 * 服务端字段名 是下划线,返回的字段名也是下划线
 *
 * msg返会的字段名  是下划线
 * 需要服务端返回之前,将下划线转换为驼峰
 * 服务端接收驼峰字段名,转换为下划线
 */
$br = "<br/>\n";
$br2 = str_repeat($br, 2);


echo '驼峰,下划线转换' . $br;
echo '驼峰转换路径' . $br;
$param = 'apiControllerUser';

var_dump(strtolower(preg_replace('/[A-Z]/', "/$0", $param)));

echo $br2 . '驼峰转换下划线' . $br;
$data = underscore($param);

var_dump($data);

/**
 * 驼峰参数转换为下划线 
 **/
function recursive($param, callable $func) {
    $data = [];
    $self = __FUNCTION__;
    if (is_array($param)) {
       foreach ($param as $k => $v) {
            $k = $self($k, $func);
            $data[$k] = $self($v, $func);
       }
       return $data;
    }

    $data= call_user_func_array($func, [$param]);

    return $data;
}

/**
 * 驼峰字符串转换为下划线字符串
 **/
function underscore($str) {
	$newStr = strtolower(preg_replace('/[A-Z]+/', '_$0', $str));
	return $newStr;
}


/**
 * 下划线字符串转换为驼峰字符串
 **/
function camelcase($str) {
    $data = preg_replace_callback('/_([a-z])/', function($matches) {return strtoupper($matches[1]);}, $str);
    return $data;

}

/**
 * 下划线字符串转换为驼峰字符串
 **/
function camelcaseUc($str) {
    $data = ucwords($str, '_'); //将字符串中每个单词的首字母转换为大写
    $data = lcfirst($data);
    $data = str_replace('_', '',  $data);  //过滤下划线
    return $data;

}


$param = [
  'reqId' => 1,
  'userId' => 3,
  'userShopId' => 64,
];

echo $br2 . '数组递归-驼峰转换下划线' . $br;
//数组递归
$data = recursive($param, 'underscore');

var_dump($data);


echo $br2 . '数组递归-下划线转换驼峰' . $br;
var_dump(recursive($data, 'camelcase'));
echo $br2 . '数组递归-下划线转换驼峰Uc' . $br;
var_dump(recursive($data, 'camelcaseUc'));



echo "方法二---------<br/>\n";
class Tool
{
    /**
     * 驼峰式键名为蛇形键名
     * 迭代转换数组中的驼峰式键名为蛇形键名(UserId=>user_id或userId=>user_id)
     * /(?<!\b)(?=[A-Z])/ '_' 不是单词开头后面以[A-Z]开始的 替换为_
     * @param	array	$array_data		要转换的数组
     * @return	areay
     */
    public static function convertKeyToSnake($array_data) {
        if (!is_array($array_data)) {
            return $array_data;
        }
        foreach ($array_data as $key => $val) {
            $field_key = preg_replace('/(?<!\b)(?=[A-Z])/', "_", $key);
            $field_key = strtolower($field_key);
            $result[$field_key] = self::convertKeyToSnake($val);
        }
        return $result;
    }

    /**
     * 蛇形键名为驼峰式键名
     * 迭代转换数组中的蛇形键名为驼峰式(user_id=>UserId)
     * /(?:_)([a-z])/ 以_开头后跟着[a-z] 将[a-z]转换为大写
     * /(?:^|_)([a-z])/ 以_开头后跟着[a-z]或者以[a-z]开头 将[a-z]转换为大写
     * @param	array	$array_data		要转换的数组
     * @return	areay
     */
    public static function convertKeyToPeak($array_data) {
        if (!is_array($array_data)) {
            return $array_data;
        }
        foreach ($array_data as $key => $val) {
            $field_key = preg_replace_callback('/(?:^|_)([a-z])/', function ($matches) {
                return strtoupper($matches[1]);
            }, $key);
            $result[$field_key] = self::convertKeyToPeak($val);
        }
        return $result;
    }

    /**
     * 蛇形键名为驼峰式,首个单词不大写
     * 迭代转换数组中的蛇形键名为驼峰式(user_id=>userId)-首个单词不大写
     * @param	array	$array_data		要转换的数组
     * @return	areay
     */
    public static function convertKeyToCamel($array_data) {
        if (!is_array($array_data)) {
            return $array_data;
        }
        $field_key = '';
        foreach ($array_data as $key => $val) {
            $field_key = preg_replace_callback('/(?:_)([a-z])/', function ($matches) {return strtoupper($matches[1]);}, $key);
            $result[$field_key] = self::convertKeyToPeak($val);
        }
        return $result;
    }
}

$data = [
    'id' => 1,
    'sub'=> ['sub_id'=>5, 'sub_name'=> '黎明'], 
    'channel_id'=> 64
];
$newData = Tool::convertKeyToPeak($data);
var_dump($newData);

$newData = Tool::convertKeyToSnake($newData);
var_dump($newData);